<!-- AI智能排班对话框组件 - 优化版本 -->
<template>
  <el-dialog
    v-model="dialogVisible"
    title="AI智能排班"
    width="1000px"
    :destroy-on-close="true"
  >
    <div class="ai-schedule-generator">
      <!-- 左右布局 -->
      <div class="ai-layout">
        <!-- 左侧：AI对话区域 -->
        <div class="ai-chat-section">
          <div class="section-header">
            <h3>AI排班助手</h3>
            <el-tag type="info">DeepSeek</el-tag>
          </div>

          <div class="chat-container">
            <!-- AI对话消息列表 -->
            <div class="message-list" ref="messageListRef">
              <div
                v-for="(message, index) in chatMessages"
                :key="index"
                :class="['message-item', message.role]"
              >
                <div class="message-avatar">
                  <el-avatar v-if="message.role === 'assistant'" :size="32">
                    <img :src="aiSvg" alt="" />
                  </el-avatar>
                  <el-avatar
                    v-else
                    :size="32"
                    style="background-color: #1890ff"
                  >
                    👤
                  </el-avatar>
                </div>
                <div class="message-content">
                  <div
                    class="message-text"
                    v-html="formatMessage(message.content)"
                  ></div>
                  <div class="message-time">
                    {{ formatTime(message.timestamp) }}
                  </div>
                </div>
              </div>
            </div>

            <!-- 输入区域 -->
            <div class="input-section">
              <!-- 统一的加载状态显示 -->
              <div v-if="loading" class="ai-loading">
                <div class="loading-content">
                  <div class="loading-animation">
                    <div class="typing-indicator">
                      <span></span>
                      <span></span>
                      <span></span>
                    </div>
                  </div>
                  <div class="loading-text">
                    <div class="loading-title">AI正在分析您的需求</div>
                    <div class="loading-subtitle">
                      请稍候，正在智能生成排班方案...
                    </div>
                  </div>
                </div>
              </div>
              <el-input
                v-model="userInput"
                type="textarea"
                :rows="2"
                placeholder="请描述您的排班需求，例如：为妇产科的张颖医生生成下周一到周六的门诊排班"
                :disabled="loading"
                @keydown.enter.exact.prevent="handleSendMessage"
                resize="none"
              />
              <div class="input-actions">
                <div class="ds-button-area">
                  <div
                    v-if="!loading"
                    class="send-area"
                    @click="handleSendMessage"
                  >
                    <div class="ds-icon">
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        viewBox="0 0 1024 1024"
                      >
                        <path
                          fill="currentColor"
                          d="m64 448 832-320-128 704-446.08-243.328L832 192 242.816 545.472zm256 512V657.024L512 768z"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <div v-else class="send-area" @click="stopOutput">
                    <div class="ds-icon-stop"></div>
                  </div>
                </div>
                <el-button @click="clearChat"> 清空对话 </el-button>
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧：生成结果确认区域 -->
        <div class="result-section">
          <div class="section-header">
            <h3>排班结果</h3>
            <el-tag :type="resultStatus.type">{{ resultStatus.text }}</el-tag>
          </div>

          <div class="result-content">
            <!-- 初始状态提示 -->
            <div v-if="!generatedData" class="empty-state">
              <el-icon size="48" color="#C0C4CC"><ChatRound /></el-icon>
              <p>请先与AI助手对话描述您的排班需求</p>
            </div>

            <!-- 生成结果预览 -->
            <div v-else class="result-preview">
              <div class="preview-header">
                <h4>生成的排班数据</h4>
                <el-tag type="success">已生成</el-tag>
              </div>

              <div class="preview-content">
                <el-descriptions :column="1" border size="small">
                  <el-descriptions-item label="匹配模板">
                    {{ matchedTemplatesCount }} 个
                  </el-descriptions-item>
                  <el-descriptions-item label="排班数量">
                    {{ generatedData.instances?.length || 0 }} 条
                  </el-descriptions-item>
                  <el-descriptions-item label="覆盖策略">
                    {{
                      formatOverwriteStrategy(generatedData.overwriteStrategy)
                    }}
                  </el-descriptions-item>
                  <el-descriptions-item label="生成时间">
                    {{ formatTime(new Date()) }}
                  </el-descriptions-item>
                </el-descriptions>

                <!-- 查询条件预览 -->
                <div v-if="currentQueryConditions" class="query-conditions">
                  <h5>查询条件</h5>
                  <el-tag
                    v-for="(value, key) in formatQueryConditions(
                      currentQueryConditions
                    )"
                    :key="key"
                    type="info"
                    size="small"
                    class="condition-tag"
                  >
                    {{ key }}: {{ value }}
                  </el-tag>
                </div>

                <!-- 排班列表预览 -->
                <div class="schedule-preview">
                  <h5>排班预览</h5>
                  <div class="preview-list">
                    <div
                      v-for="(
                        instance, index
                      ) in generatedData.instances?.slice(0, 5)"
                      :key="index"
                      class="preview-item"
                    >
                      <div class="preview-info">
                        <span class="staff-name">{{
                          instance.staff_name
                        }}</span>
                        <span class="schedule-date">{{
                          instance.schedule_date
                        }}</span>
                        <el-tag size="small">{{
                          formatTimeSlot(instance.time_slot_code)
                        }}</el-tag>
                      </div>
                    </div>
                    <div
                      v-if="generatedData.instances?.length > 5"
                      class="preview-more"
                    >
                      还有 {{ generatedData.instances.length - 5 }} 条排班...
                    </div>
                  </div>
                </div>
              </div>

              <!-- 确认操作 -->
              <div class="confirm-actions">
                <el-alert
                  title="请确认生成的排班数据"
                  description="确认后将提交到系统并生成实际的排班安排"
                  type="warning"
                  show-icon
                  :closable="false"
                />
                <div class="action-buttons">
                  <el-button @click="handleRegenerate">重新生成</el-button>
                  <el-button
                    type="primary"
                    @click="handleConfirm"
                    :loading="confirmLoading"
                  >
                    确认生成排班
                  </el-button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup>
import {
  ref,
  reactive,
  computed,
  watch,
  nextTick,
  defineProps,
  defineEmits,
} from "vue";
import { ElMessage } from "element-plus";
import { ChatRound } from "@element-plus/icons-vue";
// 加载后端API，用于AI提取关键字后查询排班模板数据
import { queryScheduleTemplateByAI } from "@/api/api";

// ================ 传入属性数据为AI智能排班提供真实数据基础 ==================
const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
  // 系统基础数据
  departmentOptions: {
    type: Array,
    default: () => [],
  },
  staffTypeOptions: {
    type: Array,
    default: () => [],
  },
  timeSlotOptions: {
    type: Array,
    default: () => [],
  },
  scheduleTypeOptions: {
    type: Array,
    default: () => [],
  },
  allStaffList: {
    type: Array,
    default: () => [],
  },
  currentScheduleInstances: {
    type: Array,
    default: () => [],
  },
  departmentList: {
    type: Array,
    default: () => [],
  },
  timeSlotList: {
    type: Array,
    default: () => [],
  },
  scheduleTypeList: {
    type: Array,
    default: () => [],
  },
  // 新增：排班模板数据
  scheduleTemplates: {
    type: Array,
    default: () => [],
  },
  // 新增：人员类型排班映射
  staffTypeScheduleMap: {
    type: Object,
    default: () => ({
      doctor: [
        "outpatient",
        "inpatient",
        "emergency",
        "surgery",
        "consultation",
        "examination",
      ],
      nurse: ["inpatient", "outpatient", "service"],
      pharmacist: ["pharmacy"],
      finance: ["billing", "registration", "office"],
      administrative: ["office"],
      manager: ["office"],
      logistics: ["service"],
    }),
  },
});

const emit = defineEmits(["update:visible", "confirm", "cancel"]);

// ==================== 组件状态 ====================
const loading = ref(false);
const confirmLoading = ref(false);
const userInput = ref("");
const messageListRef = ref(null);

// ==================== AI流式响应相关状态 ====================
const isStoppedByUser = ref(false);
const aiResponseBuffer = ref("");
const aiStreamReader = ref(null);

// ==================== 查询条件和模板数据 ====================
const currentQueryConditions = ref(null);
const matchedTemplates = ref([]);

// ======================== AI图标 ==========================
const aiSvg = require("@/assets/svg/deepseek.svg");

// ==================== 聊天数据 ====================
const chatMessages = ref([
  {
    role: "assistant",
    content:
      "您好！我是AI排班助手，我可以帮助您快速生成智能排班。\n\n请告诉我您的排班需求，例如：\n• 为妇产科的张颖医生生成下周门诊排班\n• 为所有护士生成本周排班\n• 为特定人员生成指定日期范围的排班\n\n我会理解您的需求并生成准确的排班安排。",
    timestamp: new Date(),
  },
]);

// ==================== 生成数据 ====================
const generatedData = ref(null);

// ==================== 精简系统提示词 ====================
const getSystemPrompt = () => {
  // 获取日期基准信息
  const today = new Date();
  const todayStr = today.toISOString().split("T")[0];

  // 计算下周日期范围
  const nextWeekStart = new Date(today);
  nextWeekStart.setDate(today.getDate() + ((7 - today.getDay() + 1) % 7) || 7);
  const nextWeekEnd = new Date(nextWeekStart);
  nextWeekEnd.setDate(nextWeekStart.getDate() + 6);

  const nextWeekStartStr = nextWeekStart.toISOString().split("T")[0];
  const nextWeekEndStr = nextWeekEnd.toISOString().split("T")[0];

  return {
    role: "system",
    content: `你是一个专业的医院排班助手。请根据用户需求生成查询条件来查找合适的排班模板。

当前时间基准：${todayStr}
- 今天：${todayStr}
- 下周：${nextWeekStartStr} 至 ${nextWeekEndStr}

可用查询维度：
- 科室：${props.departmentOptions.map((d) => d.label).join(", ")}
- 排班类型：${props.scheduleTypeOptions}

星期格式说明：
- 使用逗号分隔的数字，如："1,2,3,4,5"
- 1=周一, 2=周二, 3=周三, 4=周四, 5=周五, 6=周六, 7=周日

覆盖策略说明：
- skip: 跳过已有排班（默认）
- overwrite: 覆盖已有排班
- merge: 合并排班

日期范围格式：
- 使用 "YYYY-MM-DD,YYYY-MM-DD" 格式
- 例如："2024-01-01,2024-01-31"

请以严格的JSON格式返回查询条件，只包含以下字段：
{
  "department_name": "科室名称1,科室名称2",
  "staff_name": "人员姓名1,人员姓名2", 
  "schedule_type": "排班类型1,排班类型2",
  "week_days": "1,2,3,4,5",
  "date_range": "开始日期,结束日期",
  "overwrite_strategy": "skip"
}

示例响应：
{
  "department_name": "妇产科",
  "staff_name": "张颖",
  "schedule_type": "outpatient",
  "week_days": "1,2,3,4,5,6",
  "date_range": "${nextWeekStartStr},${nextWeekEndStr}",
  "overwrite_strategy": "skip"
}

重要规则：
1. 只返回JSON格式，不要有其他文本
2. 使用中文名称，不要使用编码
3. 多个值用逗号分隔，不要使用数组
4. schedule_type必须是有效可查询的排班类型名称,如："outpatient"
5. week_days必须是逗号分隔的1-7数字字符串
6. date_range必须是"开始日期,结束日期"格式，基于用户需求的时间范围
7. 默认使用"skip"覆盖策略
8. 如果某个条件不需要，可以传空字符串""`,
  };
};

// ==================== 计算属性 ====================
const dialogVisible = computed({
  get: () => props.visible,
  set: (value) => emit("update:visible", value),
});

const resultStatus = computed(() => {
  if (!generatedData.value) {
    return { type: "info", text: "等待生成" };
  }
  return { type: "success", text: "已生成" };
});

const matchedTemplatesCount = computed(() => matchedTemplates.value.length);

// ==================== 工具方法 ====================

/**
 * 格式化消息内容（支持简单换行）
 */
const formatMessage = (content) => {
  return content.replace(/\n/g, "<br>");
};

/**
 * 格式化时间显示
 */
const formatTime = (timestamp) => {
  return new Date(timestamp).toLocaleTimeString("zh-CN", {
    hour: "2-digit",
    minute: "2-digit",
  });
};

/**
 * 格式化覆盖策略
 */
const formatOverwriteStrategy = (strategy) => {
  const strategyMap = {
    skip: "跳过已有",
    overwrite: "覆盖已有",
    merge: "合并",
  };
  return strategyMap[strategy] || strategy;
};

/**
 * 格式化班次时间
 */
const formatTimeSlot = (slotCode) => {
  const slotConfig = props.timeSlotList.find(
    (item) => item.slot_code === slotCode
  );
  if (slotConfig) {
    return slotConfig.slot_name;
  }
  return slotCode;
};

/**
 * 格式化查询条件用于显示
 */
const formatQueryConditions = (conditions) => {
  const formatted = {};

  if (conditions.department_name) {
    formatted["科室"] = conditions.department_name;
  }

  if (conditions.staff_name) {
    formatted["人员"] = conditions.staff_name;
  }

  if (conditions.schedule_type) {
    formatted["排班类型"] = conditions.schedule_type;
  }

  if (conditions.week_days) {
    const dayNames = conditions.week_days.split(",").map((day) => {
      const dayMap = {
        1: "周一",
        2: "周二",
        3: "周三",
        4: "周四",
        5: "周五",
        6: "周六",
        7: "周日",
      };
      return dayMap[parseInt(day.trim())] || `周${day}`;
    });
    formatted["适用星期"] = dayNames.join(", ");
  }

  formatted["覆盖策略"] = formatOverwriteStrategy(
    conditions.overwrite_strategy
  );

  return formatted;
};

// ==================== 核心业务逻辑 ====================

/**
 * 解析AI返回的JSON查询条件
 */
const parseQueryConditions = (content) => {
  try {
    // 尝试从内容中提取JSON
    const jsonMatch = content.match(/\{[\s\S]*\}/);
    if (jsonMatch) {
      const jsonStr = jsonMatch[0];
      const conditions = JSON.parse(jsonStr);

      // 验证必需字段 - 放宽验证条件
      if (!conditions.week_days) {
        // 如果没有week_days，设置默认值为空
        conditions.week_days = null;
      }

      // 处理date_range字段
      if (conditions.date_range) {
        // 验证date_range格式
        const dateRangeArray = conditions.date_range.split(",");
        if (dateRangeArray.length !== 2) {
          console.warn("date_range格式不正确，使用默认日期范围");
          conditions.date_range = null;
        } else {
          // 验证日期格式
          const startDate = new Date(dateRangeArray[0].trim());
          const endDate = new Date(dateRangeArray[1].trim());
          if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
            console.warn("date_range包含无效日期，使用默认日期范围");
            conditions.date_range = null;
          }
        }
      } else {
        conditions.date_range = null;
      }

      let weekDaysArray = [];
      // 处理week_days格式，支持数组和字符串
      if (conditions.week_days != null) {
        if (Array.isArray(conditions.week_days)) {
          // 如果是数组格式，转换为字符串
          weekDaysArray = conditions.week_days;
          conditions.week_days = conditions.week_days.join(",");
        } else if (typeof conditions.week_days === "string") {
          // 如果是字符串，解析为数组进行验证
          weekDaysArray = conditions.week_days
            .split(",")
            .map((day) => parseInt(day.trim()))
            .filter((day) => !isNaN(day));
        } else {
          throw new Error("week_days字段格式不正确，应为字符串或数组");
        }
      }

      // 验证week_days数值范围
      const invalidDays = weekDaysArray.filter((day) => day < 1 || day > 7);
      if (invalidDays.length > 0) {
        console.warn("week_days包含无效的星期数值，使用默认值", invalidDays);
        conditions.week_days = "1,2,3,4,5,6,7";
      }

      // 设置默认覆盖策略
      if (!conditions.overwrite_strategy) {
        conditions.overwrite_strategy = "skip";
      }

      // 确保所有字段都是字符串格式
      const stringFields = ["department_name", "staff_name", "schedule_type"];
      stringFields.forEach((field) => {
        if (conditions[field]) {
          if (Array.isArray(conditions[field])) {
            conditions[field] = conditions[field].join(",");
          }
          // 如果已经是字符串，保持不变
        } else {
          conditions[field] = "";
        }
      });

      console.log("解析后的查询条件:", conditions);
      return conditions;
    }
    throw new Error("未找到有效的JSON数据");
  } catch (error) {
    console.error("解析查询条件失败:", error);
  }
};

/**
 * 根据查询条件获取排班模板
 */
const fetchScheduleTemplates = async (queryConditions) => {
  try {
    const response = await queryScheduleTemplateByAI(queryConditions);
    console.log("查询到的排班模板数据:", response.data);

    return response.data || [];
  } catch (error) {
    console.error("查询排班模板失败:", error);
    throw new Error("查询模板数据失败，请稍后重试");
  }
};

/**
 * 根据人员类型获取正确的姓名
 */
const getStaffNameByType = (template) => {
  // 优先从模板中直接获取人员信息
  if (template.staff_name) {
    return template.staff_name;
  }

  // 根据人员类型从不同字段获取姓名
  switch (template.staff_type) {
    case "doctor":
      return template.doctor_staff_name || template.staff_name || "未知医生";
    case "nurse":
      return template.nurse_staff_name || template.staff_name || "未知护士";
    case "pharmacist":
      return (
        template.pharmacist_staff_name || template.staff_name || "未知药师"
      );
    case "finance":
      return (
        template.finance_staff_name || template.staff_name || "未知财务人员"
      );
    default:
      return template.staff_name || "未知人员";
  }
};

/**
 * 生成日期范围
 */
const generateDateRange = (dateRangeStr, weeks = 2) => {
  if (dateRangeStr && dateRangeStr.trim()) {
    const dateRangeParts = dateRangeStr.split(",");
    if (dateRangeParts.length === 2) {
      const start = dateRangeParts[0].trim();
      const end = dateRangeParts[1].trim();

      // 验证日期格式
      const startDate = new Date(start);
      const endDate = new Date(end);

      if (!isNaN(startDate.getTime()) && !isNaN(endDate.getTime())) {
        return {
          start: start,
          end: end,
        };
      }
    }
  }

  // 默认生成未来2周
  const start = new Date();
  start.setDate(start.getDate() + 1); // 从明天开始

  const end = new Date(start);
  end.setDate(end.getDate() + weeks * 7 - 1);

  return {
    start: start.toISOString().split("T")[0],
    end: end.toISOString().split("T")[0],
  };
};

/**
 * 根据星期要求生成日期列表
 */
const generateDatesByWeekDays = (dateRange, weekDays) => {
  const dates = [];
  const start = new Date(dateRange.start);
  const end = new Date(dateRange.end);

  const current = new Date(start);
  while (current <= end) {
    const dayOfWeek = current.getDay() === 0 ? 7 : current.getDay(); // 转换为1-7表示周一到周日
    if (weekDays.includes(dayOfWeek)) {
      dates.push(current.toISOString().split("T")[0]);
    }
    current.setDate(current.getDate() + 1);
  }

  return dates;
};

/**
 * 根据模板创建排班实例 - 使用ScheduleGenerator.vue中的方法
 */
const createScheduleInstanceFromTemplate = (
  date,
  template,
  staff,
  notes = ""
) => {
  const dateStr = formatDate(date);

  const instance = {
    instance_id: null,
    template_id: template.schedule_id,
    schedule_date: dateStr,
    staff_type_code: template.staff_type_code,
    staff_type: template.staff_type,
    staff_id: template.staff_id,
    staff_name: staff.name,
    department_id: template.department_id,
    department_name: template.department_name,
    professional_title: template.professional_title,
    time_slot_code: template.time_slot_code,
    schedule_type: template.schedule_type,
    location:
      template.location || getLocationByType(template.schedule_type, template),
    fee_item_id: template.fee_item_id || null,
    fee_item_name: template.fee_item_name || null,
    fee_amount: template.fee_amount || null,
    max_patients:
      template.max_patients ||
      getMaxPatientsByScheduleType(template.schedule_type),
    actual_patients: 0,
    pharmacy_location: template.pharmacy_location || null,
    service_type: template.service_type || null,
    window_number: template.window_number || null,
    service_scope: template.service_scope || null,
    status: 1,
    notes:
      notes ||
      template.notes ||
      getDefaultNotes(template.schedule_type, staff, template.time_slot_code),
    avatar: staff.avatar,
    create_time: new Date().toISOString(),
    update_time: new Date().toISOString(),
  };

  return instance;
};

/**
 * 从模板数据中获取人员信息 - 使用ScheduleGenerator.vue中的方法
 */
const getStaffInfoFromTemplate = (template) => {
  let staffName = "";
  let avatar = "";

  switch (template.staff_type) {
    case "doctor":
      staffName =
        template.doctor_staff_name || template.staff_name || "未知医生";
      avatar = template.staff_avatar;
      break;
    case "nurse":
      staffName =
        template.nurse_staff_name || template.staff_name || "未知护士";
      avatar = template.staff_avatar;
      break;
    case "pharmacist":
      staffName =
        template.pharmacist_staff_name || template.staff_name || "未知药师";
      avatar = template.staff_avatar;
      break;
    case "finance":
      staffName =
        template.finance_staff_name || template.staff_name || "未知财务人员";
      avatar = template.staff_avatar;
      break;
    default:
      staffName = template.staff_name || "未知人员";
  }

  // 如果仍然没有获取到姓名，尝试从其他字段获取或使用默认值
  if (!staffName || staffName === "未知人员") {
    // 可以尝试从其他字段获取，比如直接使用模板的基本信息
    staffName = template.staff_name || `人员${template.staff_id}`;
  }

  if (!staffName) {
    console.warn("无法获取人员姓名:", template);
    return null;
  }

  return {
    id: template.staff_id,
    name: staffName,
    staff_type: template.staff_type,
    department_id: template.department_id,
    department_name: template.department_name,
    professional_title: template.professional_title,
    avatar: avatar,
  };
};

/**
 * 根据排班类型获取最大患者数 - 使用ScheduleGenerator.vue中的方法
 */
const getMaxPatientsByScheduleType = (scheduleType) => {
  const maxPatientsMap = {
    outpatient: 30,
    emergency: 20,
    surgery: 10,
    examination: 25,
    consultation: 15,
    inpatient: 0,
    pharmacy: 0,
    billing: 0,
    registration: 0,
    office: 0,
    service: 0,
  };
  return maxPatientsMap[scheduleType] || 30;
};

/**
 * 获取默认备注信息 - 使用ScheduleGenerator.vue中的方法
 */
const getDefaultNotes = (scheduleType, staff, timeSlot) => {
  return `系统自动生成 - ${staff.name}的${scheduleType}排班 - ${timeSlot}班次`;
};

/**
 * 根据排班类型和科室信息获取工作地点 - 使用ScheduleGenerator.vue中的方法
 */
const getLocationByType = (scheduleType, departmentInfo = null) => {
  const typeConfig = props.scheduleTypeOptions.find(
    (item) => item.value === scheduleType
  );
  if (!typeConfig) return "工作区域";

  const defaultLocation = typeConfig.default_location || "工作区域";

  if (departmentInfo && departmentInfo.department_name) {
    return `${departmentInfo.department_name}${defaultLocation}`;
  }
  return defaultLocation;
};

/**
 * 格式化日期为 YYYY-MM-DD - 使用ScheduleGenerator.vue中的方法
 */
const formatDate = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  return `${year}-${month}-${day}`;
};

/**
 * 判断是否为节假日 - 使用ScheduleGenerator.vue中的方法
 */
const isHoliday = (date) => {
  const holidays = [
    "2025-01-01", // 元旦
    "2025-02-10",
    "2025-02-11",
    "2025-02-12", // 春节
    "2025-04-04",
    "2025-04-05",
    "2025-04-06", // 清明
    "2025-05-01",
    "2025-05-02",
    "2025-05-03", // 劳动节
    "2025-06-10", // 端午
    "2025-09-17", // 中秋
    "2025-10-01",
    "2025-10-02",
    "2025-10-03", // 国庆
  ];
  return holidays.includes(formatDate(date));
};

/**
 * 根据模板生成排班实例 - 人工修复 — AI是大笨蛋
 */
const generateScheduleInstances = (templates, queryConditions) => {
  const instances = [];

  const overwrite_strategy = queryConditions.overwrite_strategy || "skip";
  const dateRange = generateDateRange(queryConditions.date_range, 2);
  const start = new Date(dateRange.start);
  const end = new Date(dateRange.end);

  // 选中的科室、排班类型、人员
  const selectedDepartments = queryConditions.department_name
    ? queryConditions.department_name.split(",").map((name) => name.trim())
    : [];
  // 修正：如果 schedule_type 为空字符串，则不过滤
  const selectedScheduleTypes =
    queryConditions.schedule_type && queryConditions.schedule_type.trim()
      ? queryConditions.schedule_type.split(",").map((type) => type.trim())
      : [];
  const selectedStaffNames = queryConditions.staff_name
    ? queryConditions.staff_name.split(",").map((name) => name.trim())
    : [];

  // 过滤模板
  const filteredTemplates = templates.filter((template) => {
    // 人员类型、排班类型、科室
    if (
      selectedScheduleTypes.length > 0 &&
      !selectedScheduleTypes.includes(template.schedule_type)
    )
      return false;
    if (
      selectedDepartments.length > 0 &&
      !selectedDepartments.includes(template.department_name)
    )
      return false;
    if (selectedStaffNames.length > 0) {
      const staffName = getStaffNameByType(template);
      if (!selectedStaffNames.some((name) => staffName.includes(name)))
        return false;
    }
    return template.is_active === 1;
  });

  // 修正：如果 week_days 为空，则所有日期都允许生成
  const queryWeekDays =
    queryConditions.week_days && queryConditions.week_days.trim()
      ? queryConditions.week_days.split(",").map((day) => parseInt(day.trim()))
      : null;

  const currentDate = new Date(start);
  while (currentDate <= end) {
    if (isHoliday(currentDate)) {
      currentDate.setDate(currentDate.getDate() + 1);
      continue;
    }

    const dayOfWeek = currentDate.getDay();
    const weekDay = dayOfWeek === 0 ? 7 : dayOfWeek;

    filteredTemplates.forEach((template) => {
      // 模板自身的 week_days
      const templateWeekDays = template.week_days
        ? template.week_days.split(",").map((day) => parseInt(day.trim()))
        : [];

      // 修正：如果 queryWeekDays 存在，则必须在 queryWeekDays 中；否则不过滤
      if (queryWeekDays && !queryWeekDays.includes(weekDay)) {
        return;
      }
      // 如果模板 week_days 存在，则必须在模板 week_days 中；否则不过滤
      if (templateWeekDays.length > 0 && !templateWeekDays.includes(weekDay)) {
        return;
      }

      const staff = getStaffInfoFromTemplate(template);
      if (!staff) {
        console.warn(
          `未找到人员信息: staff_id=${template.staff_id}, staff_type=${template.staff_type}`
        );
        return;
      }

      const notes =
        queryConditions.notes ||
        `AI智能生成 - ${staff.name}的${template.schedule_type}排班`;

      const instance = createScheduleInstanceFromTemplate(
        currentDate,
        template,
        staff,
        notes
      );

      instances.push(instance);
    });

    currentDate.setDate(currentDate.getDate() + 1);
  }

  return {
    instances,
    overwriteStrategy: overwrite_strategy,
    notes: `基于${filteredTemplates.length}个模板AI智能生成`,
    create_by: "AI排班",
    source_templates: filteredTemplates.map((t) => t.schedule_id),
  };
};

// ==================== AI对话处理 ====================

/**
 * 发送消息给AI
 */
const handleSendMessage = async () => {
  if (!userInput.value.trim() || loading.value) return;

  const userMessage = {
    role: "user",
    content: userInput.value,
    timestamp: new Date(),
  };

  // 添加用户消息
  chatMessages.value.push(userMessage);
  const currentInput = userInput.value;
  userInput.value = "";

  // 显示加载状态
  loading.value = true;
  isStoppedByUser.value = false;
  aiResponseBuffer.value = "";

  try {
    await callAIScheduleAPI(currentInput);
  } catch (error) {
    console.error("AI对话失败:", error);
    addAIMessage(`抱歉，处理您的请求时遇到问题：${error.message}`);
    loading.value = false;
  }
};

/**
 * 调用AI API生成查询条件
 */
const callAIScheduleAPI = async (userInput) => {
  // 构建对话历史
  const messages = [
    getSystemPrompt(),
    ...chatMessages.value
      .filter((msg) => msg.role !== "system")
      .map((msg) => ({
        role: msg.role,
        content: msg.content,
      })),
  ];

  // 添加当前用户输入
  messages.push({
    role: "user",
    content: userInput,
  });

  // 添加"正在分析中"消息
  chatMessages.value.push({
    role: "assistant",
    content: "🤔 正在分析您的排班需求...",
    timestamp: new Date(),
  });

  scrollToBottom();

  try {
    const response = await fetch("https://api.deepseek.com/chat/completions", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + process.env.VUE_APP_DEEPSEEK_API_KEY,
      },
      body: JSON.stringify({
        messages: messages,
        model: "deepseek-chat",
        max_tokens: 1024,
        temperature: 0.1,
        stream: true,
      }),
    });

    if (!response.body) {
      throw new Error("服务器未返回流数据");
    }

    const reader = response.body.getReader();
    aiStreamReader.value = reader;
    const decoder = new TextDecoder("utf-8");
    let buffer = "";
    let aiJsonResponse = ""; // 存储AI的JSON响应

    while (true) {
      if (isStoppedByUser.value) {
        await reader.cancel();
        break;
      }

      const { done, value } = await reader.read();
      if (done) {
        break;
      }

      const chunk = decoder.decode(value, { stream: true });
      buffer += chunk;

      const lines = buffer.split("\n");
      buffer = lines.pop();

      for (const line of lines) {
        if (line.startsWith("data: ")) {
          const jsonStr = line.slice(6).trim();
          if (jsonStr !== "[DONE]") {
            try {
              const jsonData = JSON.parse(jsonStr);
              const content = jsonData?.choices[0]?.delta?.content || "";

              if (content) {
                aiJsonResponse += content; // 累积AI的响应
                // 不再实时更新到聊天界面
              }
            } catch (error) {
              console.error("解析 JSON 数据失败:", error, line);
            }
          } else {
            // 流式传输完成，处理AI响应
            aiResponseBuffer.value = aiJsonResponse;
            await finalizeAIMessage();
          }
        }
      }
    }
  } catch (error) {
    console.error("AI API调用失败:", error);
    if (!isStoppedByUser.value) {
      // 移除"正在分析中"消息，添加错误消息
      chatMessages.value.pop();
      addAIMessage("❌ 抱歉，AI服务暂时不可用，请稍后重试。");
    }
  } finally {
    if (!isStoppedByUser.value) {
      loading.value = false;
    }
    aiStreamReader.value = null;
  }
};

/**
 * 完成AI消息处理
 */
const finalizeAIMessage = async () => {
  // 移除"正在分析中"消息
  const analyzingMessageIndex = chatMessages.value.findIndex(
    (msg) => msg.content === "🤔 正在分析您的排班需求..."
  );
  if (analyzingMessageIndex !== -1) {
    chatMessages.value.splice(analyzingMessageIndex, 1);
  }

  try {
    // 1. 解析查询条件
    addAIMessage("🔍 正在解析您的排班需求...");

    const queryConditions = parseQueryConditions(aiResponseBuffer.value);
    if (!queryConditions) {
      throw new Error("无法解析查询条件，请重新描述您的需求");
    }

    currentQueryConditions.value = queryConditions;

    // 2. 查询模板数据
    // 更新上一条消息为查询状态
    const lastMsg = chatMessages.value[chatMessages.value.length - 1];
    lastMsg.content = "📊 正在查询匹配的排班模板...";
    scrollToBottom();

    // 添加1秒延迟，让用户看到查询状态
    await new Promise((resolve) => setTimeout(resolve, 1000));

    matchedTemplates.value = await fetchScheduleTemplates(queryConditions);

    if (matchedTemplates.value.length === 0) {
      lastMsg.content = "❌ 未找到匹配的排班模板，请调整您的需求描述。";
      return;
    }

    // 3. 生成排班实例
    lastMsg.content = `📋 找到 ${matchedTemplates.value.length} 个匹配模板，正在生成排班实例...`;
    scrollToBottom();

    // 添加1.5秒延迟，让用户看到生成状态
    await new Promise((resolve) => setTimeout(resolve, 1500));

    generatedData.value = generateScheduleInstances(
      matchedTemplates.value,
      queryConditions
    );

    console.log("生成的排班实例数据:", generatedData.value);

    lastMsg.content = `✅ 排班数据生成完成！


请查看右侧的排班结果预览，确认无误后点击"确认生成排班"按钮。`;
  } catch (error) {
    console.error("处理AI响应失败:", error);
    // 移除之前的进度消息，添加错误消息
    if (chatMessages.value.length > 0) {
      chatMessages.value.pop();
    }
    addAIMessage(`❌ ${error.message}\n\n请重新描述您的排班需求。`);
  } finally {
    loading.value = false;
    scrollToBottom();
  }
};

/**
 * 停止AI输出
 */
const stopOutput = () => {
  isStoppedByUser.value = true;
  loading.value = false;
  if (aiStreamReader.value) {
    aiStreamReader.value.cancel();
  }
};

/**
 * 添加AI消息
 */
const addAIMessage = (content) => {
  chatMessages.value.push({
    role: "assistant",
    content: content,
    timestamp: new Date(),
  });
  scrollToBottom();
};

/**
 * 滚动到底部
 */
const scrollToBottom = () => {
  nextTick(() => {
    if (messageListRef.value) {
      messageListRef.value.scrollTop = messageListRef.value.scrollHeight;
    }
  });
};

/**
 * 清空对话
 */
const clearChat = () => {
  chatMessages.value = [
    {
      role: "assistant",
      content:
        "您好！我是AI排班助手，我可以帮助您快速生成智能排班。\n\n请告诉我您的排班需求，例如：\n• 为妇产科的张颖医生生成下周门诊排班\n• 为所有护士生成本周排班\n• 为特定人员生成指定日期范围的排班\n\n我会理解您的需求并生成准确的排班安排。",
      timestamp: new Date(),
    },
  ];
  generatedData.value = null;
  currentQueryConditions.value = null;
  matchedTemplates.value = [];
  userInput.value = "";
  aiResponseBuffer.value = "";
};

/**
 * 重新生成
 */
const handleRegenerate = () => {
  if (chatMessages.value.length > 1) {
    const lastUserMessage = chatMessages.value
      .filter((msg) => msg.role === "user")
      .pop();
    if (lastUserMessage) {
      userInput.value = lastUserMessage.content;
      handleSendMessage();
    }
  }
};

/**
 * 确认生成排班
 */
const handleConfirm = async () => {
  if (!generatedData.value) {
    ElMessage.warning("请先生成排班数据");
    return;
  }

  confirmLoading.value = true;
  try {
    // 触发确认事件，将生成的数据传递给父组件
    emit("confirm", generatedData.value);
    ElMessage.success("排班已成功生成");
    dialogVisible.value = false;
  } catch (error) {
    console.error("确认排班失败:", error);
    ElMessage.error("生成排班失败，请重试");
  } finally {
    confirmLoading.value = false;
  }
};

// ==================== 监听器 ====================
watch(dialogVisible, (newVal) => {
  if (!newVal) {
    // 对话框关闭时重置状态
    clearChat();
    loading.value = false;
    confirmLoading.value = false;
    isStoppedByUser.value = false;
    aiResponseBuffer.value = "";
    if (aiStreamReader.value) {
      aiStreamReader.value.cancel();
    }
  }
});
</script>

<style scoped>
.ai-schedule-generator {
  height: 600px;
}

.ai-layout {
  display: flex;
  height: 100%;
  gap: 16px;
}

.ai-chat-section {
  flex: 1.2;  /* 左侧稍宽一些 */
  display: flex;
  flex-direction: column;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  overflow: hidden;
}

.result-section {
  flex: 1;  /* 改为flex:1，与左侧等宽 */
  min-width: 300px; /* 设置最小宽度避免过窄 */
  display: flex;
  flex-direction: column;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  overflow: hidden;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #f5f7fa;
  border-bottom: 1px solid #e4e7ed;
}

.section-header h3 {
  margin: 0;
  font-size: 14px;
  color: #303133;
}

.chat-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.message-list {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  background: #fafafa;
}

.message-item {
  display: flex;
  margin-bottom: 16px;
  gap: 12px;
}

.message-item.user {
  flex-direction: row-reverse;
}

.message-avatar {
  flex-shrink: 0;
}

.message-content {
  max-width: 70%;
}

.message-item.user .message-content {
  text-align: right;
}

.message-text {
  padding: 12px 16px;
  border-radius: 8px;
  background: white;
  border: 1px solid #e4e7ed;
  line-height: 1.5;
  word-wrap: break-word;
}

.message-item.assistant .message-text {
  background: #ecf5ff;
  border-color: #d9ecff;
}

.message-item.user .message-text {
  background: #f0f9ff;
  border-color: #c6e2ff;
}

.message-time {
  font-size: 12px;
  color: #909399;
  margin-top: 4px;
}

/* 增强的打字指示器动画 */
.typing-indicator {
  display: flex;
  gap: 4px;
  align-items: center;
  padding: 8px 12px;
  background: white;
  border-radius: 6px;
  border: 1px solid #d9ecff;
}

.typing-indicator span {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #1890ff;
  animation: typing 1.4s infinite ease-in-out;
}

.typing-indicator span:nth-child(1) {
  animation-delay: -0.32s;
}

.typing-indicator span:nth-child(2) {
  animation-delay: -0.16s;
}

@keyframes typing {
  0%,
  80%,
  100% {
    transform: scale(0.8);
    opacity: 0.5;
  }
  40% {
    transform: scale(1);
    opacity: 1;
  }
}

/* 停止按钮样式 */
.stop-button {
  background: #ff4d4f;
}

.stop-button:hover {
  background: #ff7875;
}

.input-section {
  border-top: 1px solid #e4e7ed;
  padding: 16px;
  background: white;
}

.ai-loading {
  padding: 16px;
  background: linear-gradient(135deg, #f5f7fa 0%, #f0f9ff 100%);
  border-radius: 8px;
  margin-bottom: 12px;
  border: 1px solid #e1f5fe;
}

.loading-content {
  display: flex;
  align-items: center;
  gap: 12px;
}

.loading-animation {
  flex-shrink: 0;
}

.loading-text {
  flex: 1;
}

.loading-title {
  font-weight: 600;
  color: #1890ff;
  font-size: 14px;
  margin-bottom: 4px;
}

.loading-subtitle {
  color: #606266;
  font-size: 12px;
}

.input-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 12px;
}

.ds-button-area {
  display: flex;
  align-items: center;
  gap: 8px;
}

.send-area {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  background: #1890ff;
  color: white;
  transition: all 0.2s;
}

.send-area:hover {
  background: #40a9ff;
}

.ds-icon {
  width: 16px;
  height: 16px;
}

.ds-icon-stop {
  width: 12px;
  height: 12px;
  background: white;
  border-radius: 1px;
}

.result-content {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #909399;
  text-align: center;
}

.empty-state p {
  margin-top: 12px;
  font-size: 14px;
}

.result-preview {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.preview-header h4 {
  margin: 0;
  font-size: 14px;
  color: #303133;
}

.preview-content {
  flex: 1;
  overflow-y: auto;
}

.query-conditions {
  margin: 16px 0;
}

.query-conditions h5 {
  margin: 0 0 8px 0;
  font-size: 13px;
  color: #606266;
}

.condition-tag {
  margin: 2px 4px 2px 0;
}

.schedule-preview {
  margin-top: 16px;
}

.schedule-preview h5 {
  margin: 0 0 8px 0;
  font-size: 13px;
  color: #606266;
}

.preview-list {
  max-height: 200px;
  overflow-y: auto;
  border: 1px solid #f0f0f0;
  border-radius: 4px;
  padding: 8px;
}

.preview-item {
  padding: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.preview-item:last-child {
  border-bottom: none;
}

.preview-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
}

.staff-name {
  font-weight: 500;
  color: #303133;
}

.schedule-date {
  color: #606266;
}

.preview-more {
  text-align: center;
  color: #909399;
  font-size: 12px;
  padding: 8px;
}

.confirm-actions {
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid #e4e7ed;
}

.action-buttons {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

.action-buttons .el-button {
  flex: 1;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .ai-layout {
    flex-direction: column;
  }

  .result-section {
    width: 100%;
    height: 300px;
  }
}
</style>